package com.youxin.chat.pay.service.channel.impl.yufu;

import com.alibaba.fastjson.JSONObject;
import com.youxin.base.BaseResultCode;
import com.youxin.chat.pay.enums.CashStatusEnum;
import com.youxin.chat.pay.enums.OrderStatusEnum;
import com.youxin.chat.pay.model.ChannelAccount;
import com.youxin.chat.pay.model.ChannelOrder;
import com.youxin.chat.pay.model.UserCash;
import com.youxin.chat.pay.model.UserRecharge;
import com.youxin.chat.pay.service.channel.IPayChannel;
import com.youxin.chat.pay.enums.PayChannelEnum;
import com.youxin.chat.pay.service.channel.entity.*;

import com.youxin.chat.pay.service.channel.impl.yufu.convert.YufuErrorTransfer;
import com.youxin.chat.pay.service.channel.impl.yufu.request.*;
import com.youxin.chat.pay.service.channel.impl.yufu.response.YufuBalanceResponse;
import com.youxin.chat.pay.service.channel.impl.yufu.response.YufuDefrayNotifyResponse;
import com.youxin.chat.pay.service.channel.impl.yufu.response.YufuDefrayQueryResponse;
import com.youxin.chat.pay.service.channel.impl.yufu.util.AbstractYufuChannelUtil;
import com.youxin.chat.pay.service.channel.impl.yufu.util.YufuSignUtil;
import com.youxin.chat.pay.utils.HttpClientUtil;
import com.youxin.chat.pay.service.channel.entity.ChannelResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

@Service
public class YufuPayChannel implements IPayChannel {
    private static final Logger logger = LoggerFactory.getLogger(YufuPayChannel.class);

    @Override
    public ChannelResponse bindCard(String orderNo, ChannelBindCard channelBindCard, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);
        JSONObject jsonObject = YufuBindCard.auditBindCardRequest(orderNo, channelBindCard, channelAccount);



        YufuParamPack paramPacket = YufuSignUtil.buildParamRequestWithMd5(jsonObject, channelAccount);
        Map<String, Object> map = AbstractYufuChannelUtil.transferPackToMap(channelAccount.getChannelAccount(), paramPacket);
        logger.info("YufuPayChannel:bindCard", "裕福绑卡请求VO:,{}" + JSONObject.toJSONString(map));
        String result;
        JSONObject object;
        try {
            String url = channelAccount.getChannelUrl() + "/payment/service/sign_set.do";
            result = HttpClientUtil.httpPostRequest(url, map);
            result = URLDecoder.decode(result, "utf-8");
            logger.info("YufuPayChannel:bindCard,{}", "裕福绑卡返回结果：" + result);

            object = YufuSignUtil.unPackWithMd5(result, JSONObject.class, channelAccount);

            if (object.getString("respCode").equalsIgnoreCase("0000")) {
                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(JSONObject.toJSONString(object));
                response.setExt(object.getString("signToken"));
            } else {
                response = YufuErrorTransfer.buildPayErrorResult(object.getString("respCode"), object.getString("respDesc"));
                logger.error("请求绑卡接口失败:" + object.getString("respDesc"));
                return response;
            }

        } catch (Exception e) {
            logger.error("请求绑卡接口失败:", e);
            response.setCode(BaseResultCode.COMMON_FAIL);
            response.setErrorMsg("请求绑卡接口失败");
            return response;
        }
        response.setResult(JSONObject.toJSONString(object));

        return response;
    }

    @Override
    public ChannelResponse validateSms(ChannelBindCardSms channelBindCardSms, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);
        JSONObject jsonObject = YufuBindCard.validateBindSmsRequest(channelBindCardSms, channelAccount);

        YufuParamPack paramPacket = YufuSignUtil.buildParamRequestWithMd5(jsonObject, channelAccount);
        Map<String, Object> map = AbstractYufuChannelUtil.transferPackToMap(channelAccount.getChannelAccount(), paramPacket);
        logger.info("YufuPayChannel:validateSms,{}", "裕福绑卡短信请求VO:" + JSONObject.toJSONString(map));
        String result;
        JSONObject object;
        try {
            String url = channelAccount.getChannelUrl() + "/payment/service/sign.do";
            result = HttpClientUtil.httpPostRequest(url, map);
            result = URLDecoder.decode(result, "utf-8");
            logger.info("YufuPayChannel:validateSms,{}", "裕福绑卡短信返回结果：" + result);

            object = YufuSignUtil.unPackWithMd5(result, JSONObject.class, channelAccount);

            if (object.getString("respCode").equalsIgnoreCase("0000") && object.getString("transStatus").equalsIgnoreCase("01")) {
                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(JSONObject.toJSONString(object));
                response.setAgreementId(object.getString("signId"));
                response.setExt(channelBindCardSms.getOrderNo());
            } else {
                response = YufuErrorTransfer.buildPayErrorResult(object.getString("respCode"), object.getString("respDesc"));

                logger.error("请求绑卡验证接口失败:" + object.getString("respDesc"));
                return response;
            }
        } catch (Exception e) {
            logger.error("签约短信验证失败:", e);
            response.setCode(BaseResultCode.COMMON_FAIL);
            response.setErrorMsg("请求接口异常");
            return response;
        }
        return response;
    }

    @Override
    public boolean support(String channelCode) {
        return PayChannelEnum.YUFU.getChannelCode().equalsIgnoreCase(channelCode);
    }

    @Override
    public ChannelResponse pay(ChannelPay channelPay, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);
        JSONObject jsonObject = YufuPay.buildPayRequest(channelPay, channelAccount);

        YufuParamPack paramPacket = YufuSignUtil.buildParamRequestWithMd5(jsonObject, channelAccount);
        Map<String, Object> map = AbstractYufuChannelUtil.transferPackToMap(channelAccount.getChannelAccount(), paramPacket);
        logger.info("YufuPayChannel:pay,{}", "裕福支付请求VO:" + JSONObject.toJSONString(map));
        String result;
        JSONObject object;
        try {
            String url = channelAccount.getChannelUrl() + "/payment/service/payset.do";
            result = HttpClientUtil.httpPostRequest(url, map);
            result = URLDecoder.decode(result, "utf-8");
            logger.info("YufuPayChannel:pay,{}", "裕福支付返回结果：" + result);

            object = YufuSignUtil.unPackWithMd5(result, JSONObject.class, channelAccount);

            if (object.getString("respCode").equalsIgnoreCase("0000")) {
                Map<String, String> dataMap = new HashMap<>();
                dataMap.put("token", object.getString("token"));
                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(JSONObject.toJSONString(object));
                response.setExt(JSONObject.toJSONString(dataMap));
            } else {
                response = YufuErrorTransfer.buildPayErrorResult(object.getString("respCode"), object.getString("respDesc"));
                logger.error("请求支付接口失败:" + object.getString("respDesc"));
                return response;
            }
        } catch (Exception e) {
            logger.error("裕福支付失败:", e);
            response.setCode(BaseResultCode.COMMON_FAIL);
            response.setErrorMsg("请求接口异常");
            return response;
        }
        return response;
    }

    @Override
    public ChannelResponse termination(ChannelTerminationCard channelTerminationCard, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);
        JSONObject jsonObject = YufuTermination.buildTerminationRequest(channelTerminationCard);

        YufuParamPack paramPacket = YufuSignUtil.buildParamRequestWithMd5(jsonObject, channelAccount);
        Map<String, Object> map = AbstractYufuChannelUtil.transferPackToMap(channelAccount.getChannelAccount(), paramPacket);
        logger.info("YufuPayChannel:termination,{}", "裕福解绑卡请求VO:" + JSONObject.toJSONString(map));
        String result;
        JSONObject object;
        try {
            String url = channelAccount.getChannelUrl() + "/payment/service/sign_relieve.do";
            result = HttpClientUtil.httpPostRequest(url, map);
            result = URLDecoder.decode(result, "utf-8");
            logger.info("YufuPayChannel:termination,{}", "裕福解绑卡返回结果：" + result);

            object = YufuSignUtil.unPackWithMd5(result, JSONObject.class, channelAccount);

            if (object.getString("respCode").equalsIgnoreCase("0000")) {
                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(JSONObject.toJSONString(object));
            } else {
                response = YufuErrorTransfer.buildPayErrorResult(object.getString("respCode"), object.getString("respDesc"));

                response.setErrorMsg("请求绑卡接口失败");
                logger.error("请求绑卡接口失败:" + object.getString("respDesc"));
                return response;
            }
        } catch (Exception e) {
            logger.error("请求支付接口失败:", e);
            response.setErrorMsg("请求支付接口失败");
            return response;
        }
        return response;
    }

    @Override
    public ChannelNotifyResponse orderNotify(ChannelNotifyRequest request, ChannelAccount channelAccount) {
        ChannelNotifyResponse channelNotifyResponse = new ChannelNotifyResponse();
        channelNotifyResponse.setOrderNo(request.getOrderNo());
        channelNotifyResponse.setStatus(OrderStatusEnum.NOT_PAY.getStatus());
        channelNotifyResponse.setResponseText("FAIL");
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject = YufuSignUtil.unPackWithMd5(request.getData(), JSONObject.class, channelAccount);
            logger.info("data={}", jsonObject.toJSONString());
            if ("0000".equalsIgnoreCase(jsonObject.getString("respCode"))) {
                if ("01".equalsIgnoreCase(jsonObject.getString("transStatus"))) {
                    JSONObject object = new JSONObject();
                    object.put("retCode", "AUP00000");
                    object.put("retMsg", "交易成功");
                    channelNotifyResponse.setResponseText(object.toJSONString());
                    channelNotifyResponse.setOrderNo(request.getOrderNo());
                    channelNotifyResponse.setStatus(OrderStatusEnum.PAY_SUCCESS.getStatus());
                } else if ("02".equalsIgnoreCase(jsonObject.getString("transStatus"))) {
                    JSONObject object = new JSONObject();
                    object.put("retCode", "FAIL");
                    object.put("retMsg", "交易失败");
                    channelNotifyResponse.setResponseText(object.toJSONString());
                    channelNotifyResponse.setOrderNo(request.getOrderNo());
                    channelNotifyResponse.setStatus(OrderStatusEnum.PAY_FAIL.getStatus());
                } else if ("05".equalsIgnoreCase(jsonObject.getString("transStatus"))) {
                    JSONObject object = new JSONObject();
                    object.put("retCode", "FAIL");
                    object.put("retMsg", "支付取消");
                    channelNotifyResponse.setResponseText(object.toJSONString());
                    channelNotifyResponse.setOrderNo(request.getOrderNo());
                    channelNotifyResponse.setStatus(OrderStatusEnum.PAY_FAIL.getStatus());
                }
            }
        } catch (Exception e) {
            logger.error("请求支付接口失败:", e);
            channelNotifyResponse.setOrderNo(jsonObject.getString("merchantOrderId"));
            channelNotifyResponse.setStatus(OrderStatusEnum.PAY_FAIL.getStatus());
            return channelNotifyResponse;

        }
        return channelNotifyResponse;
    }

    @Override
    public ChannelNotifyResponse defrayNotify(ChannelNotifyRequest request, ChannelAccount channelAccount) {
        logger.info("YufuDefray:defrayNotify,{}", "裕福代付参数通知:" + request.getData());
        ChannelNotifyResponse response = new ChannelNotifyResponse();
        response.setOrderNo(request.getOrderNo());
        response.setStatus(OrderStatusEnum.NOT_PAY.getStatus());
        response.setResponseText("FAIL");
        try {
            YufuDefrayNotifyResponse yufuResponse = YufuSignUtil.unPackWithMd5(request.getData(), YufuDefrayNotifyResponse.class, channelAccount);
            if ("05".equalsIgnoreCase(yufuResponse.getTransStatus())) {
                response.setStatus(OrderStatusEnum.PAY_SUCCESS.getStatus());
                return response;
            } else if ("04".equalsIgnoreCase(yufuResponse.getTransStatus())) {
                response.setStatus(OrderStatusEnum.PAY_FAIL.getStatus());
                return response;
            }

        } catch (Exception e) {
            logger.error("代付通知异常", e);
            response.setResponseText("代付通知异常");
            return response;
        }
        return response;
    }

    @Override
    public ChannelResponse payQuery(ChannelOrder channelOrder, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);

        JSONObject jsonObject = YufuPay.buildPayExceptionRequest(channelOrder, channelAccount);

        YufuParamPack paramPacket = YufuSignUtil.buildParamRequestWithMd5(jsonObject, channelAccount);
        Map<String, Object> map = AbstractYufuChannelUtil.transferPackToMap(channelAccount.getChannelAccount(), paramPacket);
        logger.info("YufuPayChannel:payQuery,{}", "裕福支付查询请求VO:" + JSONObject.toJSONString(map));
        String result;
        JSONObject object;
        try {
            String url = channelAccount.getChannelUrl() + "/payment/query.do";
            result = HttpClientUtil.httpPostRequest(url, map);
            result = URLDecoder.decode(result, "utf-8");
            logger.info("YufuPayChannel:payQuery,{}", "裕福支付查询返回结果：" + result);

            object = YufuSignUtil.unPackWithMd5(result, JSONObject.class, channelAccount);

            if (object.getString("respCode").equalsIgnoreCase("0000") && object.getString("transStatus").equalsIgnoreCase("01")) {
                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(JSONObject.toJSONString(object));
            } else {
                response = YufuErrorTransfer.buildPayErrorResult(object.getString("respCode"), object.getString("respDesc"));
                logger.error("请求支付查询接口失败:" + object.getString("retMsg"));
                return response;
            }
        } catch (Exception e) {
            logger.error("请求支付查询接口失败:", e);
            response.setErrorMsg("请求支付查询接口失败:");
            return response;
        }
        response.setResult(JSONObject.toJSONString(object));
        return response;
    }

    @Override
    public ChannelResponse defray(ChannelDefray channelDefray, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);

        YufuCreateDefrayRequest request = YufuPay.buildDefrayRequest(channelDefray, channelAccount);
        logger.info("YufuDefray:defray,{}", "裕福代付请求VO：" + JSONObject.toJSONString(request));
        String url = channelAccount.getChannelUrl() + "/batchpay/realTimeApply.do";
        String result;
        try {
            YufuParamPack paramPack = YufuSignUtil.buildParamRequestWithMd5(request, channelAccount);
            Map<String, Object> map = AbstractYufuChannelUtil.transferPackToMap(channelAccount.getChannelAccount(), paramPack);
            result = HttpClientUtil.httpPostRequest(url, map);
            result = URLDecoder.decode(result, "utf-8");
            logger.info("YufuDefray:defray,{}", "请求裕福代付返回结果：" + result);
            YufuDefrayQueryResponse yufuResponse = YufuSignUtil.unPackWithMd5(result, YufuDefrayQueryResponse.class, channelAccount);
            logger.info("YufuDefray:defrayQuery,{}", "请求裕福代付返回结果：" + JSONObject.toJSONString(response));
            if ("0000".equalsIgnoreCase(yufuResponse.getRespCode())) {
                response.setResult(JSONObject.toJSONString(yufuResponse));
                String status = yufuResponse.getTransStatus();
                if ("05".equalsIgnoreCase(status)) {
                    response.setStatus(CashStatusEnum.SUCCESS.getStatus());
                } else if ("01".equalsIgnoreCase(status) || "04".equalsIgnoreCase(status)) {
                    response.setStatus(CashStatusEnum.FAIL.getStatus());
                } else {
                    response.setStatus(CashStatusEnum.AUDIT.getStatus());
                }
            } else {
                response = YufuErrorTransfer.buildDefrayErrorResult(yufuResponse.getRespCode(), yufuResponse.getRespDesc());
                response.setStatus(CashStatusEnum.FAIL.getStatus());
                return response;
            }
            return response;
        } catch (Exception e) {
            logger.error("请求代付接口失败:", e);
            response.setErrorMsg("请求代付接口失败:");
            return response;
        }
    }

    @Override
    public ChannelResponse defrayQuery(UserCash userCash, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);

        YufuDefrayQueryRequest request = YufuPay.buildDefrayQueryRequest(userCash.getCashNo(), channelAccount);
        logger.info("YufuDefray:defrayQuery,{}", "裕福代付查询请求VO：" + JSONObject.toJSONString(request));
        String url = channelAccount.getChannelUrl() + "/batchpay/realTimeQuery.do";
        String result;
        try {
            YufuParamPack paramPack = YufuSignUtil.buildParamRequestWithMd5(request, channelAccount);
            Map<String, Object> map = AbstractYufuChannelUtil.transferPackToMap(channelAccount.getChannelAccount(), paramPack);
            result = HttpClientUtil.httpPostRequest(url, map);
            result = URLDecoder.decode(result, "utf-8");
            logger.info("YufuDefray:defrayQuery,{}", "请求裕福代付查询返回结果：" + result);
            YufuDefrayQueryResponse yufuResponse = YufuSignUtil.unPackWithMd5(result, YufuDefrayQueryResponse.class, channelAccount);
            logger.info("YufuDefray:defrayQuery", "请求裕福代付查询返回结果：,{}" + JSONObject.toJSONString(response));
            if ("RT-0008".equalsIgnoreCase(yufuResponse.getRespCode()) || "104020002".equalsIgnoreCase(yufuResponse.getRespCode())) {
                response.setStatus(CashStatusEnum.AUDIT.getStatus());
                response.setResult(JSONObject.toJSONString(yufuResponse));
                return response;
            }
            if ("0000".equalsIgnoreCase(yufuResponse.getRespCode())) {
                response.setResult(JSONObject.toJSONString(yufuResponse));
                String status = yufuResponse.getTransStatus();
                if ("05".equalsIgnoreCase(status)) {
                    response.setStatus(CashStatusEnum.SUCCESS.getStatus());
                } else if ("01".equalsIgnoreCase(status) || "04".equalsIgnoreCase(status) || "06".equalsIgnoreCase(status)) {
                    response.setStatus(CashStatusEnum.FAIL.getStatus());
                } else {
                    response.setStatus(CashStatusEnum.AUDIT.getStatus());
                }
            } else {
                response = YufuErrorTransfer.buildDefrayErrorResult(yufuResponse.getRespCode(), yufuResponse.getRespDesc());
                response.setStatus(CashStatusEnum.FAIL.getStatus());
                return response;
            }
            return response;
        } catch (Exception e) {
            logger.error("请求支付接口失败:", e);
            response.setErrorMsg("请求支付接口失败:");
            return response;
        }
    }

    @Override
    public ChannelResponse doChargeSms(ChannelChargeSms channelChargeSms, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);
        JSONObject jsonObject = YufuPay.doChargeSmsRequest(channelChargeSms, channelAccount.getChannelAccount());

        YufuParamPack paramPacket = YufuSignUtil.buildParamRequestWithMd5(jsonObject, channelAccount);
        Map<String, Object> map = AbstractYufuChannelUtil.transferPackToMap(channelAccount.getChannelAccount(), paramPacket);
        logger.info("YufuPayChannel:doChargeSms,{}", "裕福支付短信请求VO:" + JSONObject.toJSONString(map));
        String result;
        JSONObject object;
        try {
            String url = channelAccount.getChannelUrl() + "/payment/service/pay.do";
            result = HttpClientUtil.httpPostRequest(url, map);
            result = URLDecoder.decode(result, "utf-8");
            logger.info("YufuPayChannel:doChargeSms,{}", "裕福支付短信返回结果：" + result);

            object = YufuSignUtil.unPackWithMd5(result, JSONObject.class, channelAccount);

            if (object.getString("respCode").equalsIgnoreCase("0000")) {
                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(JSONObject.toJSONString(object));

            } else {
                response = YufuErrorTransfer.buildPayErrorResult(object.getString("respCode"), object.getString("respDesc"));

                logger.error("请求支付验证接口失败:" + object.getString("respDesc"));
                return response;
            }
        } catch (Exception e) {
            logger.error("支付短信验证失败:", e);
            response.setCode(BaseResultCode.COMMON_FAIL);
            response.setErrorMsg("请求接口异常");
            return response;
        }
        return response;
    }

    @Override
    public ChannelResponse balanceQuery(ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);

        JSONObject jsonObject = YufuBalance.buildBalanceRequest(channelAccount);
        logger.info("YufuDefray:balanceQuery,{}", "裕福余额查询请求VO：" + JSONObject.toJSONString(jsonObject));
        String url = channelAccount.getChannelUrl() + "/batchpay/balanceInquiry.do";
        String result;
        try {
            YufuParamPack paramPack = YufuSignUtil.buildParamRequestWithMd5(jsonObject, channelAccount);
            Map<String, Object> map = AbstractYufuChannelUtil.transferPackToMap(channelAccount.getChannelAccount(), paramPack);
            result = HttpClientUtil.httpPostRequest(url, map);
            result = URLDecoder.decode(result, "utf-8");
            logger.info("YufuDefray:balanceQuery,{}", "请求裕福余额查询返回结果：" + result);
            YufuBalanceResponse yufuBalanceResponse = YufuSignUtil.unPackWithMd5(result, YufuBalanceResponse.class, channelAccount);
            logger.info("YufuDefray:balanceQuery,{}", "请求裕福余额查询返回结果：" + JSONObject.toJSONString(yufuBalanceResponse));
            if ("0000".equalsIgnoreCase(yufuBalanceResponse.getRespCode())) {
                response.setResult(JSONObject.toJSONString(yufuBalanceResponse));
                Map<String, BigDecimal> repMap = new HashMap<>();
                repMap.put("balance", new BigDecimal(yufuBalanceResponse.getBalance()));
                repMap.put("availableBalance", new BigDecimal(yufuBalanceResponse.getAvailableBalance()));
                repMap.put("lockAmount", new BigDecimal(yufuBalanceResponse.getBalance()).subtract(new BigDecimal(yufuBalanceResponse.getAvailableBalance())));
                response.setExt(JSONObject.toJSONString(repMap));
            } else {
                response = YufuErrorTransfer.buildDefrayErrorResult(yufuBalanceResponse.getRespCode(), yufuBalanceResponse.getRespDesc());
                response.setStatus(CashStatusEnum.FAIL.getStatus());
                response.setCode(BaseResultCode.COMMON_FAIL);
                return response;
            }
            return response;
        } catch (Exception e) {
            response.setCode(BaseResultCode.INTERNAL_ERROR);
            logger.error("请求余额查询接口失败:", e);
            response.setErrorMsg("请求余额查询接口失败:");
            return response;
        }
    }
}
